import random

from python_nlp.xfaiss.flask_faiss_on_mongo_test import search
from python_nlp.kg.neo4j.config import NEO4J_CONFIG_CBLUE_DETAIL
from neo4j import GraphDatabase
from PyCmpltrtok.common import sep

DIS_THRESH = 20.0


def get_symptom(driver, xwords, xlimit=4):
    """从一组词语中找出xlimit个是症状的节点的名字"""
    if not xwords:
        return []
    assert(isinstance(xlimit, int) and xlimit > 0)
    xlist = []
    with driver.session() as ss:
        for xword in xwords:
            cypher = "MATCH (n:Node{name:%r}) WHERE n.type CONTAINS %r RETURN n.name" % (xword, '症状', )
            print(cypher)
            xresult = ss.run(cypher)
            if xresult:
                for xelement in xresult:
                    if len(xlist) >= xlimit:
                        return xlist
                    xlist.append(xelement[0])
    return xlist


def diagnose(driver, symptoms):
    """从一组症状中做出诊断。"""
    if not symptoms:
        return None
    symptoms = list(symptoms)
    random.shuffle(symptoms)
    with driver.session() as ss:
        cypher = ''
        for xword in symptoms:
            cypher += "OPTIONAL MATCH (n:Node{name:%r})-[r:Predicate{name:'临床表现'}]-(m) WHERE n.type CONTAINS %r\n" % (xword, '症状', )
        cypher += 'RETURN DISTINCT m.name'
        print(cypher)
        xresult = ss.run(cypher)
        if xresult:
            xdiseases = []
            for i, xelement in enumerate(xresult):
                xdiseases.append(xelement[0])
            return xdiseases
    return None


if '__main__' == __name__:

    def _main():

        print('Connecting neo4j ...')
        driver = GraphDatabase.driver(**NEO4J_CONFIG_CBLUE_DETAIL)
        print('Connected to neo4j.')

        print(f'请输入您的症状，输入q退出。')

        dis_set = None

        while True:
            sep()
            print('请输入症状:')
            xinput = input().strip()
            if 'q' == xinput.lower():
                print('Bye!')
                break

            # 搜索输入，选出距离小于阈值的结果
            xoutput = search(xinput, 10)
            xsents = xoutput['sentences']
            xds = xoutput['D']
            print('候选:')
            xwords = []
            for i, s in enumerate(xsents):
                d = xds[i]
                print(i, s, d, d < DIS_THRESH)
                if d < DIS_THRESH:
                    xwords.append(s)

            # 从这些结果中挑选出是“临床表现”的节点名字
            xlist = get_symptom(driver, xwords)
            print(f'输入了症状：{xlist}')

            # 用这些临床表现去诊断
            xdiseases = diagnose(driver, xlist)
            if xdiseases is None:
                print('本轮没有找到相关疾病。')
            else:
                print(f'本轮诊断：{xdiseases}')
                if dis_set is None:
                    # 第一次诊断
                    dis_set = set(xdiseases)
                else:
                    # 后续诊断
                    xresult = dis_set.intersection(set(xdiseases))  # 求交集
                    if not len(xresult):  # 没有交集求并集
                        print('没有交集求并集')
                        xresult = dis_set.union(set(xdiseases))
                    dis_set = xresult
            print(f'诊断：{dis_set}')

    _main()
